import { Logger } from './logger';
import { IDebuggerConfig } from './debugConfig';

export interface IDataBreakpoint {
    id: number;
    address: string;
    accessType: 'read' | 'write' | 'readWrite';
    condition?: string;
    hitCondition?: string;
    size?: number;
    enabled: boolean;
}

export interface IDataBreakpointInfo {
    dataId: string;
    description: string;
    accessTypes: ('read' | 'write' | 'readWrite')[];
    canPersist: boolean;
}

export class DataBreakpointManager {
    private logger: Logger;
    private config: IDebuggerConfig;
    private dataBreakpoints: Map<number, IDataBreakpoint>;
    private nextBreakpointId: number;

    constructor(config: IDebuggerConfig) {
        this.config = config;
        this.logger = Logger.getInstance();
        this.dataBreakpoints = new Map();
        this.nextBreakpointId = 1;
    }

    public addDataBreakpoint(breakpoint: Omit<IDataBreakpoint, 'id'>): number {
        const id = this.nextBreakpointId++;
        const newBreakpoint: IDataBreakpoint = {
            ...breakpoint,
            id
        };
        this.dataBreakpoints.set(id, newBreakpoint);
        this.logger.debug(`Added data breakpoint: ${JSON.stringify(newBreakpoint)}`);
        return id;
    }

    public removeDataBreakpoint(id: number): void {
        this.dataBreakpoints.delete(id);
        this.logger.debug(`Removed data breakpoint: ${id}`);
    }

    public getDataBreakpoint(id: number): IDataBreakpoint | undefined {
        return this.dataBreakpoints.get(id);
    }

    public getAllDataBreakpoints(): IDataBreakpoint[] {
        return Array.from(this.dataBreakpoints.values());
    }

    public setDataBreakpointEnabled(id: number, enabled: boolean): void {
        const breakpoint = this.dataBreakpoints.get(id);
        if (breakpoint) {
            breakpoint.enabled = enabled;
            this.logger.debug(`Set data breakpoint ${id} enabled: ${enabled}`);
        }
    }

    public setDataBreakpointCondition(id: number, condition: string): void {
        const breakpoint = this.dataBreakpoints.get(id);
        if (breakpoint) {
            breakpoint.condition = condition;
            this.logger.debug(`Set data breakpoint ${id} condition: ${condition}`);
        }
    }

    public setDataBreakpointHitCondition(id: number, hitCondition: string): void {
        const breakpoint = this.dataBreakpoints.get(id);
        if (breakpoint) {
            breakpoint.hitCondition = hitCondition;
            this.logger.debug(`Set data breakpoint ${id} hit condition: ${hitCondition}`);
        }
    }

    public getDataBreakpointInfo(variableName: string): IDataBreakpointInfo {
        return {
            dataId: variableName,
            description: `监视 '${variableName}' 的变化`,
            accessTypes: ['read', 'write', 'readWrite'],
            canPersist: true
        };
    }

    public evaluateDataBreakpoint(
        id: number,
        accessType: 'read' | 'write',
        oldValue: any,
        newValue: any
    ): boolean {
        const breakpoint = this.dataBreakpoints.get(id);
        if (!breakpoint || !breakpoint.enabled) {
            return false;
        }

        // 检查访问类型
        if (breakpoint.accessType === 'read' && accessType === 'write') {
            return false;
        }
        if (breakpoint.accessType === 'write' && accessType === 'read') {
            return false;
        }

        // 评估条件
        if (breakpoint.condition) {
            try {
                const condition = breakpoint.condition
                    .replace('${oldValue}', JSON.stringify(oldValue))
                    .replace('${newValue}', JSON.stringify(newValue));

                if (!new Function('return ' + condition)()) {
                    return false;
                }
            } catch (error) {
                this.logger.error(`Error evaluating data breakpoint condition: ${error}`);
                return false;
            }
        }

        // 评估命中条件
        if (breakpoint.hitCondition) {
            try {
                const hitCondition = breakpoint.hitCondition
                    .replace('${oldValue}', JSON.stringify(oldValue))
                    .replace('${newValue}', JSON.stringify(newValue));

                if (!new Function('return ' + hitCondition)()) {
                    return false;
                }
            } catch (error) {
                this.logger.error(`Error evaluating data breakpoint hit condition: ${error}`);
                return false;
            }
        }

        return true;
    }

    public formatDataBreakpointInfo(breakpoint: IDataBreakpoint): string {
        let info = `数据断点 ID: ${breakpoint.id}\n`;
        info += `地址: ${breakpoint.address}\n`;
        info += `访问类型: ${this.formatAccessType(breakpoint.accessType)}\n`;

        if (breakpoint.condition) {
            info += `条件: ${breakpoint.condition}\n`;
        }

        if (breakpoint.hitCondition) {
            info += `命中条件: ${breakpoint.hitCondition}\n`;
        }

        if (breakpoint.size) {
            info += `大小: ${breakpoint.size} 字节\n`;
        }

        info += `状态: ${breakpoint.enabled ? '启用' : '禁用'}`;

        return info;
    }

    private formatAccessType(accessType: 'read' | 'write' | 'readWrite'): string {
        switch (accessType) {
            case 'read': return '读取';
            case 'write': return '写入';
            case 'readWrite': return '读取/写入';
            default: return '未知';
        }
    }

    public dispose(): void {
        this.dataBreakpoints.clear();
    }
} 